
import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * 
 */

/**
 * @author Max
 *
 */
public class VendingMachineTest {
	// The number of slots in the vending machine
	public static final int NUM_SLOTS = 4;

	// The code for the "A" slot
	public static final String A_CODE = "A";

	// The code for the "B" slot
	public static final String B_CODE = "B";
	
	// The code for the "C" slot
	public static final String C_CODE = "C";
	
	// The code for the "D" slot
	public static final String D_CODE = "D";
	
	VendingMachine vm;
	VendingMachineItem vmItem1;
	VendingMachineItem vmItem2;
	VendingMachineItem vmItem3;
	VendingMachineItem vmItem4;
	
	/**
	 * @throws java.lang.Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		vm = new VendingMachine();
		vmItem1 = new VendingMachineItem("coke", 1.5);
		vmItem2 = new VendingMachineItem("fanta", 1);
		vmItem3 = new VendingMachineItem("pepsi", 2);
		vmItem4 = new VendingMachineItem("water", 2);
	}
	
	@Test
	public void testVendingMachine(){
		assertEquals(null, vm.getItem("A")); //test if array[0] is null
		assertEquals(null, vm.getItem("B")); //test if array[1] is null
		assertEquals(null, vm.getItem("C")); //test if array[2] is null
		assertEquals(null, vm.getItem("D")); //test if array[3] is null
		assertEquals(0, vm.getBalance() , 0); //test if balance is 0
		
	}
	
	@Test
	public void testAddItem(){
		vm.addItem(vmItem1, "A"); //add 4 items to each slot		
		vm.addItem(vmItem2, "B");
		vm.addItem(vmItem3, "C");
		vm.addItem(vmItem4, "D");
		
		VendingMachineItem item1 = vm.getItem("A");
		VendingMachineItem item2 = vm.getItem("B");
		VendingMachineItem item3 = vm.getItem("C");
		VendingMachineItem item4 = vm.getItem("D");
		
		assertEquals("coke", item1.getName()); //test if names of the items in itemArray are the same as inserted values after items are added
		assertEquals("fanta", item2.getName()); 
		assertEquals("pepsi", item3.getName());
		assertEquals("water", item4.getName());
		
		assertEquals(1.5, item1.getPrice(), 0); //test if prices of the items are the same as inserted values after items are added
		assertEquals(1, item2.getPrice(), 0);
		assertEquals(2, item3.getPrice(), 0);
		assertEquals(2, item4.getPrice(), 0);
	}
	
	@Test (expected = VendingMachineException.class)
	public void testAddItemException(){
		vm.addItem(vmItem1, "A"); 		
		vm.addItem(vmItem1, "A"); //test if program go through exception when an item is inserted to the occupied slot
	}
	
	@Test (expected = VendingMachineException.class)
	public void testAddItemException2(){
		vm.addItem(vmItem1, "E"); 		
	}
	
	@Test
	public void testRemoveItem(){
		vm.addItem(vmItem1, "A");
		VendingMachineItem item = vm.removeItem("A");
		
		assertEquals("coke", item.getName()); //test if name of returned item from testRemoveItem is the same as expected value
		assertEquals(1.5, item.getPrice(), 0); //test if price of returned item from testRemoveItem is the same as expected value
		
		assertEquals(null, vm.getItem("A")); //test if the slot of itemArray in which item existed is empty after item is removed
	}
	
	@Test (expected = VendingMachineException.class)
	public void testRemoveItemException(){
		VendingMachineItem item = vm.removeItem("A");  //test if program go through exception when an item is removed from the empty slot
	}
	
	
	@Test
	public void testInsertMoney(){
		vm.insertMoney(2);
		vm.insertMoney(1.5);
		assertEquals(3.5, vm.getBalance(), 0); //test if balance of vendingMachine is the same as inserted money
	}
	
	@Test (expected = VendingMachineException.class)
	public void testInsertMoneyException(){
		vm.insertMoney(-1); //test if program go through exception when a negative number is inserted as money
	}
	
	@Test
	public void testGetBalance(){
		vm.insertMoney(2.5);
		assertEquals(2.5, vm.getBalance(), 0); //test amount of balance after money is inserted
		
		vm.addItem(vmItem1, "A");
		vm.makePurchase("A");
		assertEquals(1, vm.getBalance(), 0); //test amount of balance after makePurchase
	}
	
	@Test
	public void testMakePurchase(){
		vm.addItem(vmItem1, "A"); //add 2 items 		
		vm.addItem(vmItem3, "C");
		
		vm.insertMoney(2.5);
		
		assertEquals(true, vm.makePurchase("A")); //test if makePurchase returns true when item != null and balance >= price
		assertEquals(false, vm.makePurchase("B")); //test if makePurchase returns true when item == null and balance >= price
		assertEquals(false, vm.makePurchase("C")); //test if makePurchase returns true when item != null and balance < price
		assertEquals(false, vm.makePurchase("D")); //test if makePurchase returns true when item == null and balance < price
	}
	
	@Test
	public void testReturnChange(){
		vm.insertMoney(2.5);
		
		assertEquals(2.5, vm.returnChange(), 0); //test if returnChange() returns correct change after money is inserted
		
		vm.addItem(vmItem1, "A");
		vm.insertMoney(2.5);
		vm.makePurchase("A");
		
		assertEquals(1, vm.returnChange(), 0); //test if returnChange() returns correct change after makePurchase()
	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
	}

	
	
}
